﻿// Author:Alexis
// Blog: http://www.cnblogs.com/alexis/

using System;
using Hammock;
using System.IO.IsolatedStorage;
using Newtonsoft.Json;
using System.Net;
using System.Windows;
using Hammock.Authentication.OAuth;
using Hammock.Web;

namespace vDisk.WindowsPhone
{
    /// <summary>
    /// 微盘SDK主服务类
    /// Author:Alexis
    /// Blog: http://www.cnblogs.com/alexis/
    /// </summary>
    public class NetService
    {
        RestClient restClient;
        UserLogin login = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public NetService()
        {
            restClient = new RestClient()
            {
                Authority = Constants.ApiUrl,
                HasElevatedPermissions = true,
            };
            login = null;
            login = new UserLogin();

            if (IsolatedStorageSettings.ApplicationSettings.Contains("UserToken"))
            {
                login.Token = IsolatedStorageSettings.ApplicationSettings["UserToken"].ToString();
            }
            if (IsolatedStorageSettings.ApplicationSettings.Contains("DoLogid"))
            {
                login.DoLogid = IsolatedStorageSettings.ApplicationSettings["DoLogid"].ToString();
            }
            RequestHelper.login = login;
        }

        /// <summary>
        /// 一些不需要参数的请求服务:保持同步、保持Token、获取容量信息、清空回收站
        /// </summary>
        /// <param name="type">Service类型</param>
        public void CommonRequest(ServiceType type)
        {
            restClient.Authority = Constants.ApiUrl;
            if (type == ServiceType.Keep)
            {
                restClient.BeginRequest(RequestHelper.GetKeepRequest(), (e1, e2, e3) => AsyncCallback(e1, e2, e3, type));
            }
            else if (type == ServiceType.KeepToken)
            {
                restClient.BeginRequest(RequestHelper.GetKeepTokenRequest(), (e1, e2, e3) => AsyncCallback(e1, e2, e3, type));
            }
            else if (type == ServiceType.GetQuota)
            {
                restClient.BeginRequest(RequestHelper.GetQuotaRequest(), (e1, e2, e3) => AsyncCallback(e1, e2, e3, type));
            }
            else if (type == ServiceType.Recycle_Clear)
            {
                restClient.BeginRequest(RequestHelper.GetRecycleClearRequest(), (e1, e2, e3) => AsyncCallback(e1, e2, e3, type));
            }
        }

        public delegate void ServiceCallBack(bool isSuccess, object response, string errmsg = "");
        public ServiceCallBack ServicecallBack { get; set; }

        #region 登录
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="username">账号</param>
        /// <param name="password">密码</param>
        public void Login(string username, string password)
        {
            getToken(username, password);
        }
        #endregion

        #region 获取Token
        /// <summary>
        /// 获取Token
        /// </summary>
        /// <param name="email">账户</param>
        /// <param name="password">密码</param>
        private void getToken(string email, string password)
        {
            restClient.Authority = Constants.ApiUrl;
            restClient.RetryPolicy = new Hammock.Retries.RetryPolicy()
            {
                RetryCount = 0,
            };
            restClient.BeginRequest(RequestHelper.GetTokenRequest(email, password), (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.GetToken));
        }
        #endregion

        #region 上传文件
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="uploadCmd">上传参数</param>
        public void Upload(UploadFileReq uploadCmd)
        {
            restClient.Method = WebMethod.Post;

            OAuthCredentials credentials = new OAuthCredentials()
            {
                Type = OAuthType.ProtectedResource,
                Token = login.Token,
                ParameterHandling = OAuthParameterHandling.UrlOrPostParameters,
            };

            restClient.BeginRequest(RequestHelper.GetUploadFileRequest(uploadCmd),
                (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.UploadFile));
        }
        #endregion

        #region 创建目录
        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="createName">新建目录名称</param>
        /// <param name="parentName">父目录名字（根目录为“”）</param>
        /// <param name="parentId">父目录ID（跟目录为“0”）</param>
        public void CreateDir(string createName, string parentName, string parentId)
        {
            restClient.BeginRequest(RequestHelper.GetCreateDirRequest(createName, parentName, parentId),
                (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.CreateDir));
        }
        #endregion

        #region 获得列表
        /// <summary>
        /// 获得列表
        /// </summary>
        /// <param name="page">当前页码，缺省为1</param>
        /// <param name="pageSize">每页条数，缺省为1024，最小为2</param>
        /// <param name="dir_id">目录id</param>
        public void GetList(string page = "1", string pageSize = "1024", string dir_id = "0")
        {
            restClient.BeginRequest(RequestHelper.GetListRequest(page, pageSize, dir_id),
                (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.GetList));
        }
        #endregion

        #region 获得单个文件信息
        /// <summary>
        /// 获得单个文件信息
        /// </summary>
        /// <param name="fid">文件id</param>
        public void GetFileInfo(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetDeleteDirRequest(fid)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.GetFileInfo));
        }
        #endregion

        #region 删除目录
        /// <summary>
        /// 删除目录
        /// </summary>
        /// <param name="dir_id">目录id</param>
        private void DeleteDir(string dir_id)
        {
            if (string.IsNullOrEmpty(dir_id) || string.Compare(dir_id, "") == 0)
            {
                return;
            }
            restClient.BeginRequest(RequestHelper.GetDeleteDirRequest(dir_id)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.DeleteDir));

        }
        #endregion

        #region 删除文件
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="fid">文件id</param>
        public void DeleteFile(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetDeleteFileRequest(fid)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.DeleteFile));
        }
        #endregion

        #region 复制文件
        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="fid">文件id</param>
        /// <param name="new_name">副本的名称</param>
        /// <param name="to_dir_id">目标目录的id，跟目录值为0</param>
        public void CopyFile(string fid, string new_name, string to_dir_id)
        {
            restClient.BeginRequest(RequestHelper.GetCopyFileRequest(fid, new_name, to_dir_id)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.CopyFile));

        }
        #endregion

        #region 移动文件
        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="fid">文件id</param>
        /// <param name="new_name">移动后的文件名</param>
        /// <param name="to_dir_id">目标目录的id，跟目录值为0</param>
        public void MoveFile(string fid, string new_name, string to_dir_id)
        {
            restClient.BeginRequest(RequestHelper.GetMoveFileRequest(fid, new_name, to_dir_id)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.MoveFile));
        }
        #endregion

        #region 文件重命名
        /// <summary>
        /// 文件重命名
        /// </summary>
        /// <param name="fid">文件id</param>
        /// <param name="new_name">新文件名</param>
        public void RenameFile(string fid, string new_name)
        {
            restClient.BeginRequest(RequestHelper.GetRenameFileRequest(fid, new_name)
                , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.RenameFile));
        }
        #endregion

        #region 目录重命名
        /// <summary>
        /// 目录重命名
        /// </summary>
        /// <param name="dir_id">目录id</param>
        /// <param name="new_name">新文件名</param>
        public void RenameDir(string dir_id, string new_name)
        {
            restClient.BeginRequest(RequestHelper.GetRenameDirRequest(dir_id, new_name)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.RenameDir));
        }
        #endregion

        #region 移动目录
        /// <summary>
        /// 移动目录
        /// </summary>
        /// <param name="dir_id">目录id(不能为0)</param>
        /// <param name="new_name">新名称</param>
        /// <param name="to_parent_id">目标父目录id, 根目录值为: 0</param>
        public void MoveDir(string dir_id, string new_name, string to_parent_id)
        {
            restClient.BeginRequest(RequestHelper.GetMoveDirRequest(dir_id, new_name, to_parent_id)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.MoveDir));
        }
        #endregion

        #region 分享文件
        /// <summary>
        /// 分享文件
        /// </summary>
        /// <param name="fid">文件id</param>
        public void ShareFile(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetShareFileRequest(fid)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.ShareFile));
        }
        #endregion

        #region 取消分享
        /// <summary>
        /// 取消分享
        /// </summary>
        /// <param name="fid">文件id</param>
        public void CancelShareFile(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetShareFileRequest(fid, false)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.CancelShareFile));
        }
        #endregion

        #region 获得回收站列表
        /// <summary>
        /// 获得回收站列表
        /// </summary>
        /// <param name="page_size">每页显示条数</param>
        /// <param name="page">第几页</param>
        public void GetRecycleList(string page_size, string page)
        {
            restClient.BeginRequest(RequestHelper.GetRecycleListRequest(page_size, page)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.Recycle_GetList));
        }
        #endregion

        #region 从回收站中彻底删除一个文件
        /// <summary>
        /// 从回收站中彻底删除一个文件
        /// </summary>
        /// <param name="fid">文件id</param>
        public void DeleteRecycelFile(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetRecycleDeleteFileRequest(fid)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.Recycle_DeleteFile));
        }
        #endregion

        #region 从回收站中彻底删除一个目录
        /// <summary>
        /// 从回收站中彻底删除一个目录
        /// </summary>
        /// <param name="dir_id">目录id</param>
        public void DeleteRecycelDir(string dir_id)
        {
            restClient.BeginRequest(RequestHelper.GetRecycleDeleteDirRequest(dir_id)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.Recycle_DeleteDir));
        }
        #endregion

        #region 从回收站中还原一个文件
        /// <summary>
        /// 从回收站中还原一个文件
        /// </summary>
        /// <param name="fid">文件id</param>
        public void RestoreRecycleFile(string fid)
        {
            restClient.BeginRequest(RequestHelper.GetRecycleRestoreFileRequest(fid)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.Recycle_RestoreFile));
        }
        #endregion

        #region 从回收站中还原一个目录
        /// <summary>
        /// 从回收站中还原一个目录
        /// </summary>
        /// <param name="dir_id">目录id</param>
        public void RestoreRecycleDir(string dir_id)
        {
            restClient.BeginRequest(RequestHelper.GetRecycleRestoreFileRequest(dir_id)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.Recycle_RestoreDir));
        }
        #endregion

        #region 通过路径得到目录id
        /// <summary>
        /// 通过路径得到目录id
        /// </summary>
        /// <param name="path">路径</param>
        public void GetDiridWithPath(string path)
        {
            restClient.BeginRequest(RequestHelper.GetDiridWithPathRequest(path)
                            , (e1, e2, e3) => AsyncCallback(e1, e2, e3, ServiceType.GetDiridWithPath));
        }
        #endregion

        /// <summary>
        /// 异步callback
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="response">response</param>
        /// <param name="userState">userState</param>
        /// <param name="type">Service类型</param>
        internal void AsyncCallback(RestRequest request, RestResponse response, object userState, ServiceType type)
        {
            if (response.StatusCode == HttpStatusCode.OK)
            {
                ResponseBase res = JsonConvert.DeserializeObject<ResponseBase>(response.Content);
                if (res != null && res.err_code == "0")//Success
                {
                    switch (type)
                    {
                        case ServiceType.Keep:
                        case ServiceType.DeleteFile:
                        case ServiceType.DeleteDir:
                        case ServiceType.RenameFile:
                        case ServiceType.RenameDir:
                        case ServiceType.CancelShareFile:
                        case ServiceType.Recycle_Clear:
                        case ServiceType.Recycle_DeleteFile:
                        case ServiceType.Recycle_DeleteDir:
                        case ServiceType.Recycle_RestoreFile:
                        case ServiceType.Recycle_RestoreDir:
                            var gid = JsonConvert.DeserializeObject<CommonResponseBase>(response.Content);
                            SaveDologid(gid.dologid);
                            ServicecallBack(true, gid, gid.err_msg);
                            break;
                        case ServiceType.GetToken:
                            TokenResponse values = JsonConvert.DeserializeObject<TokenResponse>(response.Content);
                            login = new UserLogin()
                            {
                                Token = values.data.token,
                            };
                            IsolatedStorageSettings.ApplicationSettings["UserToken"] = login.Token;
                            IsolatedStorageSettings.ApplicationSettings["DoLogid"] = string.Empty;
                            IsolatedStorageSettings.ApplicationSettings.Save();
                            ServicecallBack(true, values, "Success");
                            break;
                        case ServiceType.KeepToken:
                            ServicecallBack(true, JsonConvert.DeserializeObject<CommonResponse>(response.Content));
                            break;
                        case ServiceType.UploadFile:
                            UploadResponse resUpload = JsonConvert.DeserializeObject<UploadResponse>(response.Content);
                            SaveDologid(resUpload.dologid);
                            ServicecallBack(true, resUpload);
                            break;
                        case ServiceType.UploadFileShare:
                            break;
                        case ServiceType.CopyFile:
                        case ServiceType.MoveFile:
                            var file = JsonConvert.DeserializeObject<FileResponse>(response.Content);
                            SaveDologid(file.dologid);
                            ServicecallBack(true, file);
                            break;
                        case ServiceType.GetList:
                        case ServiceType.Recycle_GetList:
                            var listItem = JsonConvert.DeserializeObject<vDiskListIem>(response.Content);
                            ServicecallBack(true, listItem);
                            break;
                        case ServiceType.GetQuota:
                            var quota = JsonConvert.DeserializeObject<QuotaResponse>(response.Content);
                            SaveDologid(quota.dologid);
                            ServicecallBack(true, quota);
                            break;
                        case ServiceType.UploadWithSha1:
                            break;
                        case ServiceType.GetFileInfo:
                            var fileinfo = JsonConvert.DeserializeObject<vDiskFileResponse>(response.Content);
                            SaveDologid(fileinfo.dologid);
                            ServicecallBack(true, fileinfo);
                            break;
                        case ServiceType.ShareFile:
                            break;
                        case ServiceType.CreateDir:
                        case ServiceType.MoveDir:
                        case ServiceType.GetDiridWithPath:
                            var path = JsonConvert.DeserializeObject<DirResponse>(response.Content);
                            SaveDologid(path.dologid);
                            ServicecallBack(true, path);
                            break;
                        case ServiceType.Dologid:
                            break;
                        default:
                            break;
                    }
                }
                else if (res != null)
                {
                    if (res.err_code == "602")//dologid old
                    {
                        SaveDologid(JsonConvert.DeserializeObject<CommonResponseBase>(response.Content).dologid);
                    }
                    else
                    {
                        ServicecallBack(false, res, res.err_msg);
                    }
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(response.Content))
                {
                    ServicecallBack(false, null, response.Content);
                }
                else
                {
                    ServicecallBack(false, null, "unknown error");
                }
            }
        }

        /// <summary>
        /// 保存dologid
        /// </summary>
        /// <param name="id">id值</param>
        private void SaveDologid(string id)
        {
            IsolatedStorageSettings.ApplicationSettings["DoLogid"] = id;
            IsolatedStorageSettings.ApplicationSettings.Save();
        }
    }

    /// <summary>
    /// 服务类型
    /// </summary>
    public enum ServiceType
    {
        /// <summary>
        /// 保持同步
        /// </summary>
        Keep,
        /// <summary>
        /// 获得token
        /// </summary>
        GetToken,
        /// <summary>
        /// 保持token
        /// </summary>
        KeepToken,
        /// <summary>
        /// 文件上传(10M以内)
        /// </summary>
        UploadFile,
        /// <summary>
        /// 上传文件并分享(10M以下)
        /// </summary>
        UploadFileShare,
        /// <summary>
        /// 创建目录
        /// </summary>
        CreateDir,
        /// <summary>
        /// 获得列表
        /// </summary>
        GetList,
        /// <summary>
        /// 获得容量信息
        /// </summary>
        GetQuota,
        /// <summary>
        /// 无文件上传(sha1)
        /// </summary>
        UploadWithSha1,
        /// <summary>
        /// 获得单个文件信息
        /// </summary>
        GetFileInfo,
        /// <summary>
        /// 删除目录
        /// </summary>
        DeleteDir,
        /// <summary>
        /// 删除文件
        /// </summary>
        DeleteFile,
        /// <summary>
        /// 复制文件
        /// </summary>
        CopyFile,
        /// <summary>
        /// 移动文件
        /// </summary>
        MoveFile,
        /// <summary>
        /// 文件重命名
        /// </summary>
        RenameFile,
        /// <summary>
        /// 目录重命名
        /// </summary>
        RenameDir,
        /// <summary>
        /// 移动目录
        /// </summary>
        MoveDir,
        /// <summary>
        /// 分享文件
        /// </summary>
        ShareFile,
        /// <summary>
        /// 取消分享
        /// </summary>
        CancelShareFile,
        /// <summary>
        /// 获得回收站列表
        /// </summary>
        Recycle_GetList,
        /// <summary>
        /// 清空回收站
        /// </summary>
        Recycle_Clear,
        /// <summary>
        /// 从回收站中彻底删除一个文件
        /// </summary>
        Recycle_DeleteFile,
        /// <summary>
        /// 从回收站中彻底删除一个目录
        /// </summary>
        Recycle_DeleteDir,
        /// <summary>
        /// 从回收站中还原一个文件
        /// </summary>
        Recycle_RestoreFile,
        /// <summary>
        /// 从回收站中还原一个目录
        /// </summary>
        Recycle_RestoreDir,
        /// <summary>
        /// 通过路径得到目录id
        /// </summary>
        GetDiridWithPath,
        /// <summary>
        /// dologid机制,请求方式: POST、GET方式请求接口
        /// </summary>
        Dologid,
        //返回格式: JSON，返回结果有2项数据dologid和dologdir
        //请求参数:
        //dologid: 本地最新dologid（可以缺省），如果携带的dologid在服务器上不是最新的，所有写操作将会被拒绝。并返回最新dologid和需要更新的dirid
    }
}